/*
** __SaM__'s Particle System
** Copyright (C) 2007 - 2008, Antonenko Artem
**
** shaParticleManager source file
*/

#include "../../include/shaparticle.h"


shaParticleManager::shaParticleManager(bool delOldPS)
{
	nPS = 0;
	tX = tY = 0.0f;
	b_delOldPS = delOldPS;
	psList = 0;
	partAlive = 0;
}

shaParticleManager::~shaParticleManager()
{
	shaParticleManagerItem *pItem = psList, *pNext = 0;

	while (pItem)
	{
		pNext = pItem->next;
		delete pItem->ps;
		delete pItem;
		pItem = pNext;
	}
}

void shaParticleManager::Update(float dt)
{
	shaParticleManagerItem *pItem = psList, *pPrev = 0;
	partAlive = 0;

	while (pItem)
	{
		pItem->ps->Update(dt);
		partAlive += pItem->ps->GetParticlesAlive();
		if (pItem->ps->GetGraphTime() == -2.0f && pItem->ps->GetParticlesAlive() == 0 && b_delOldPS)
		{
			delete pItem->ps;
			if (pPrev)
			{
				pPrev->next = pItem->next;
			}
			else
			{
				psList = pItem->next;
			}

			delete pItem;
			nPS--;

			if (pPrev)
			{
				pItem = pPrev->next;
			}
			else
			{
				pItem = psList;
			}
			continue;
		}
		pPrev = pItem;
		pItem = pItem->next;
	}
}

void shaParticleManager::Render()
{
	shaParticleManagerItem *pItem = psList;

	while (pItem)
	{
		pItem->ps->Render();
		pItem = pItem->next;
	}
}

shaParticleSystem* shaParticleManager::SpawnPS(shaParticleSystemInfo *psi, float x, float y)
{
	if (nPS == MAX_PSYSTEMS)
	{
		return 0;
	}
	
	shaParticleManagerItem *pNew = 0, *pItem = psList, *pPrev = 0;

	pNew = new shaParticleManagerItem;
	pNew->ps = new shaParticleSystem(psi);
	pNew->ps->FireAt(x, y);
	pNew->ps->Transpose(tX, tY);
	pNew->next = 0;
	
	while (pItem)
	{
		pPrev = pItem;
		pItem = pItem->next;
	}
	
	if (pPrev)
	{
		pPrev->next = pNew;
	}
	else
	{
		psList = pNew;
	}
	nPS++;

	return pNew->ps;
}

bool shaParticleManager::IsPSAlive(shaParticleSystem *ps) const
{
	shaParticleManagerItem *pItem = psList;

	while (pItem)
	{
		if (pItem->ps == ps)
		{
			return true;
		}
		pItem = pItem->next;
	}
	return false;
}

void shaParticleManager::Transpose(float x, float y)
{
	shaParticleManagerItem *pItem = psList;

	while (pItem)
	{
		pItem->ps->Transpose(x, y);
		pItem = pItem->next;
	}

	tX = x;
	tY = y;
}

void shaParticleManager::KillPS(shaParticleSystem *ps)
{
	shaParticleManagerItem* pItem = psList, *pPrev = 0;

	while (pItem)
	{
		if (pItem->ps == ps)
		{
			delete pItem->ps;
			if (pPrev)
			{
				pPrev->next = pItem->next;
			}
			else
			{
				psList = pItem->next;
			}
			delete pItem;
			nPS--;
			break;
		}
		pPrev = pItem;
		pItem = pItem->next;
	}
	if(nPS <= 0) {
		psList = 0;
		nPS = 0;
	}
}

void shaParticleManager::KillAll()
{
	shaParticleManagerItem *pItem = psList, *pNext = 0;

	while (pItem)
	{
		pNext = pItem->next;
		delete pItem->ps;
		delete pItem;
		pItem = pNext;
	}
	nPS = 0;
	psList = 0;
}

void shaParticleManager::StopAll(void) {
	shaParticleManagerItem *pItem = psList;

	while(pItem) {
		pItem->ps->Stop();
		pItem = pItem->next;
	}
}

shaParticleSystem*	shaParticleManager::GetPS(int n)
{
	if (n < 0 || n >= nPS)
	{
		return NULL;
	}
	
	shaParticleManagerItem* pItem = psList;

	for (int i = 0; i < n; i++)
	{
		pItem = pItem->next;
	}

	return pItem->ps;
}

void shaParticleManager::SwapPSs(int first, int second)
{
	if (first < 0 || first >= nPS)
	{
		return;
	}
	if (second < 0 || second >= nPS)
	{
		return;
	}

	shaParticleManagerItem *pFirst = psList, *pSecond = psList, *pPrev = 0;
	shaParticleSystem* pPS = 0;
	int i;

	for (i = 0; i < min(first, second); i++)
	{
		pPrev = pFirst;
		pFirst = pPrev->next;
	}
	
	pSecond = pFirst;

	for (i; i < max(second, first); i++)
	{
		pPrev = pSecond;
		pSecond = pPrev->next;
	}

	pPS	= pFirst->ps;
	pFirst->ps = pSecond->ps;
	pSecond->ps = pPS;
}
